package com.lv.fast.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lv.fast.DO.SysUserDO;
import com.lv.fast.DTO.SysMenuDTO;
import com.lv.fast.DTO.SysRoleDTO;
import com.lv.fast.DTO.SysUserDTO;
import com.lv.fast.DTO.SysUserPageQuery;
import com.lv.fast.VO.SysUserVO;
import com.lv.fast.dao.SysUserDao;
import com.lv.fast.enums.RestResultEnum;
import com.lv.fast.enums.UserStatusEnum;
import com.lv.fast.service.SysRoleService;
import com.lv.fast.service.SysUserService;
import com.lv.fast.util.*;
import lombok.AllArgsConstructor;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author jie.lv
 */
@Service
@AllArgsConstructor
public class SysUserServiceImpl implements SysUserService {

    private final SysUserDao sysUserDao;

    private final SysRoleService roleService;

    @Override
    public SysUserDTO getSysUserByUniqueKey(String key){
        Assert.assertNotNull(key, "根据唯一关键字获取用户时唯一关键字不能为空");
        QueryWrapper<SysUserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", key);
        queryWrapper.or();
        queryWrapper.eq("user_name", key);
        queryWrapper.or();
        queryWrapper.eq("mobile", key);
        queryWrapper.notIn("user_status", UserStatusEnum.DELETED.getCode());
        SysUserDO sysUserDO = sysUserDao.selectOne(queryWrapper);
        if (sysUserDO == null){
            return null;
        }
        SysUserDTO sysUserDTO = BeanUtil.copyProperties(sysUserDO, SysUserDTO.class);
        return sysUserDTO;
    }

    @Override
    public SysUserDTO getSysUserById(String userId, boolean isContainsRoles){
        Assert.assertNotNull(userId, "根据userId获取用户时userId不能为空");
        QueryWrapper<SysUserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", userId);
        queryWrapper.notIn("user_status", UserStatusEnum.DELETED.getCode());
        SysUserDO sysUserDO = sysUserDao.selectOne(queryWrapper);
        if (sysUserDO == null){
            return null;
        }
        SysUserDTO sysUserDTO = BeanUtil.copyProperties(sysUserDO, SysUserDTO.class);
        if (isContainsRoles){
            appendRoles(sysUserDTO, true);
        }
        return sysUserDTO;
    }

    @Override
    public SysUserDTO appendRoles(SysUserDTO userDTO, boolean isContainsMenus){
        if (userDTO == null){
            return null;
        }
        if (isContainsMenus){
            LinkedHashSet<SysRoleDTO> roles = roleService.listUserRoleByUserId(userDTO.getId(), true);
            LinkedHashSet<SysMenuDTO> menus = roles.stream().map(SysRoleDTO::getMenus).collect(LinkedHashSet::new, LinkedHashSet::addAll, LinkedHashSet::addAll);
            userDTO.setRoles(roles);
            userDTO.setMenus(menus);
            return userDTO;
        }
        LinkedHashSet<SysRoleDTO> sysRoleDTOS = roleService.listUserRoleByUserId(userDTO.getId(), false);
        userDTO.setRoles(sysRoleDTOS);
        return userDTO;
    }

    @Override
    public IPage<SysUserVO> list(SysUserPageQuery pageQuery){
        QueryWrapper<SysUserDO> queryWrapper = QueryWrapperUtil.getPageQueryWrapper(pageQuery, "name");
        queryWrapper.notIn("user_status", UserStatusEnum.DELETED.getCode());
        Page<SysUserDO> pageDO = sysUserDao.selectPage(PageUtil.getPage(pageQuery), queryWrapper);
        IPage<SysUserVO> sysUserVOIPage = PageUtil.pageBeanConvert(pageDO, SysUserVO.class);
        return sysUserVOIPage;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean add(SysUserDTO sysUserDTO){
        Assert.assertNotNull(sysUserDTO, "用户对象不能为空");
        SysUserDO sysUserDO = BeanUtil.copyProperties(sysUserDTO, SysUserDO.class);
        String id = String.valueOf(IdWorker.getId());
        sysUserDO.setId(id);
        sysUserDO.setCreatedBy(SysUserUtil.getCurrentLoginUserId());
        sysUserDO.setUpdatedBy(SysUserUtil.getCurrentLoginUserId());
        sysUserDO.setPassword(BCrypt.hashpw(sysUserDO.getPassword().toLowerCase()));
        sysUserDao.insert(sysUserDO);
        LinkedHashSet<SysRoleDTO> roles = sysUserDTO.getRoles();
        if (CollectionUtil.isNotEmpty(roles)){
            Set<String> roleIds = roles.stream().map(SysRoleDTO::getId).collect(Collectors.toSet());
            sysUserDao.batchInsertUserRole(id, roleIds);
        }
        return true;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean update(SysUserDTO sysUserDTO){
        Assert.assertNotNull(sysUserDTO, "用户对象不能为空");
        String id = sysUserDTO.getId();
        Assert.assertNotNull(id, "用户Id不能为空");
        SysUserDTO sysUserById = getSysUserById(id, false);
        Assert.assertNotNull(sysUserById, RestResultEnum.DATABASE_NOT_EXIST_ERROR);
        String email = sysUserDTO.getEmail();
        if (StringUtils.isNotBlank(email)){
            SysUserDTO sysUserByUniqueKey = getSysUserByUniqueKey(email);
            Assert.assertIsTrue(sysUserByUniqueKey != null, RestResultEnum.DATABASE_EXIST_ERROR);
        }
        String name = sysUserDTO.getName();
        if (StringUtils.isNotBlank(name)){
            SysUserDTO sysUserByUniqueKey = getSysUserByUniqueKey(name);
            Assert.assertIsTrue(sysUserByUniqueKey != null, RestResultEnum.DATABASE_EXIST_ERROR);
        }
        String mobile = sysUserDTO.getMobile();
        if (StringUtils.isNotBlank(mobile)){
            SysUserDTO sysUserByUniqueKey = getSysUserByUniqueKey(mobile);
            Assert.assertIsTrue(sysUserByUniqueKey != null, RestResultEnum.DATABASE_EXIST_ERROR);
        }
        LinkedHashSet<SysRoleDTO> roles = sysUserDTO.getRoles();
        if (CollectionUtil.isNotEmpty(roles)){
            SecurityUtils.getSubject().checkPermission("sys:user:manage");
            // 删除用户所有角色
            sysUserDao.deleteUserRoleByUserId(id);
            // 新增用户角色关系
            Set<String> roleIds = roles.stream().map(SysRoleDTO::getId).collect(Collectors.toSet());
            sysUserDao.batchInsertUserRole(id, roleIds);
        }
        //修改用户信息
        SysUserDO sysUserDO = BeanUtil.copyProperties(sysUserDTO, SysUserDO.class);
        sysUserDao.updateById(sysUserDO);
        String password = sysUserDO.getPassword();
        if (StringUtils.isNotBlank(password)){
            //清除本地缓存
            SysUserUtil.removeUserPassword(id);
        }
        // 清除本地缓存
        SysUserUtil.removeUser(id);
        return true;
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public boolean delete(String userId){
        Assert.assertNotNull(userId, "用户Id不能为空");
        SysUserDTO sysUser = getSysUserById(userId, false);
        Assert.assertNotNull(sysUser, RestResultEnum.DATABASE_NOT_EXIST_ERROR);
        // 删除用户所有角色
        sysUserDao.deleteUserRoleByUserId(userId);
        // 逻辑删除用户
        SysUserDO sysUserDO = new SysUserDO();
        sysUserDO.setId(userId);
        sysUserDO.setStatus(UserStatusEnum.DELETED.getCode());
        sysUserDao.updateById(sysUserDO);
        // 清除本地缓存
        SysUserUtil.removeUser(userId);
        SysUserUtil.removeUserPassword(userId);
        return true;
    }
}
